
#include <stdlib.h>
#include "ndk_JNIArray.h"

static jstring globalStr;
static jfieldID j_name2 = NULL;

int compare(const void* number1,const void* number2)
{
	int* num1 = (int*) number1;
	int* num2 = (int*) number2;
	return *num1 - *num2;
}

JNIEXPORT void JNICALL Java_ndk_JNIArray_sort
  (JNIEnv *env, jclass jcls, jintArray jarray)
{
	jint* intArray = (*env)->GetIntArrayElements(env,jarray,NULL);
	
	int length = (*env)->GetArrayLength(env,jarray);
	/*
	 * 参数一：void* 数组的首地址
	 * 参数二：数组长度
	 * 参数三：数组元素数据类型大小
	 * 参数四：数组的一个比较函数指针
	 * */
	qsort(intArray,length,sizeof(int),compare);

	/*
	 * 同步数据给Java层数组，intArray并是不jarray
	 * 0:			既要同步数据给jarray，又要释放intArray
	 * JNI_COMMIT: 	会同步jarray数据，但不会释放intArray
	 * jni_ABORT:	不会同步jarray数据，但是会释放intArray
	 * */
	(*env)->ReleaseIntArrayElements(env,jarray,intArray,0);

}


JNIEXPORT void JNICALL Java_ndk_JNIArray_localRef
  (JNIEnv *env, jclass jclz)
{
	// native创建的对象由谁管理？最大能开辟多大的内存？
	// native创建的对象，在使用完毕之后需要手动释放
	jclass str_clz = (*env)->FindClass(env,"java/lang/String");
	jmethodID j_mid = (*env)->GetMethodID(env,str_clz,"<init>","()V");
	jobject j_str = (*env)->NewObject(env,str_clz,j_mid);

	printf("准备回收局部变量\n");
	// 局部变量不在使用的情况下，需要手动回收，阅读JvmGC源码
	(*env)->DeleteLocalRef(env,j_str);
	printf("回收局部变量完毕\n");

}

JNIEXPORT void JNICALL Java_ndk_JNIArray_deleteGlobalRef
  (JNIEnv *env, jclass jclz)
{
	if (globalStr != NULL)
	{
		printf("全局变量不为空，准备回收\n");
		(*env)->DeleteGlobalRef(env,globalStr);
		printf("回收全局变量完毕\n");
	}
}  

JNIEXPORT void JNICALL Java_ndk_JNIArray_saveGlobalRef
  (JNIEnv *env, jclass jclz,jstring jstr)
{	
	// 保存全局变量
	globalStr = (*env)->NewGlobalRef(env,jstr);
}  

JNIEXPORT jstring JNICALL Java_ndk_JNIArray_getGlobalRef
  (JNIEnv *env, jclass jclz)
{
	return globalStr;
} 

JNIEXPORT void JNICALL Java_ndk_JNIArray_initStaticCache
  (JNIEnv *env, jclass jclz)
{
	j_name2 = (*env)->GetStaticFieldID(env,jclz,"name2","Ljava/lang/String;");
}

JNIEXPORT void JNICALL Java_ndk_JNIArray_staticLocalCache
  (JNIEnv *env, jclass jclz, jstring nickname)
{
	static jfieldID j_id = NULL;
	if (j_id == NULL)
	{
		printf("j_id is NULL！\n");
		j_id = (*env)->GetStaticFieldID(env,jclz,"name","Ljava/lang/String;");
	} else {
		printf("j_id已经存在！\n");
	}
	
	(*env)->SetStaticObjectField(env,jclz,j_id,nickname);
	// 对全局初始化的name2进行赋值
	(*env)->SetStaticObjectField(env,jclz,j_name2,nickname);

}


JNIEXPORT void JNICALL Java_ndk_JNIArray_handleException
  (JNIEnv *env, jclass jclz)
{
	// 获取Java层中一个不存在的属性
	j_name2 = (*env)->GetStaticFieldID(env,jclz,"name999","Ljava/lang/String;");
	
	jthrowable throwable = (*env)->ExceptionOccurred(env);
	if(throwable)
	{
		// native发生异常的处理方式一：补救，但首先做的是清理异常
		(*env)->ExceptionClear(env);
		// 重新获取name2
		j_name2 = (*env)->GetStaticFieldID(env,jclz,"name2","Ljava/lang/String;");
	}
	// 再制造出来一个异常，然后抛出给Java层
	j_name2 = (*env)->GetStaticFieldID(env,jclz,"name3","Ljava/lang/String;");
	throwable = (*env)->ExceptionOccurred(env);
	if(throwable)
	{
		// native发生异常的处理方式一：补救，但首先做的是清理异常
		(*env)->ExceptionClear(env);
		// 构建一个Java层异常对象
		jclass no_such_clz = (*env)->FindClass(env,"java/lang/NoSuchFieldException");
		(*env)->ThrowNew(env,no_such_clz,"NoSuchFieldException name3");
		// 向Java层抛出异常后，尽量不要继续进行了
		return;
	}

}
